/////////////////////////////////////////////////////////////////////////
//
// Amuse Engine - graphics/platform/win32
// Copyright (c) 2014.  All Rights Reserved
//
// File:		AERenderContext.cpp
// Author:		Gianluca Belardelli
// Date:		05/09/2014
//
/////////////////////////////////////////////////////////////////////////
#include <AEEngine.h>

#define DEFAULT_PRIORITY	1000.0f

AERenderContext *AERenderContext::m_lpCurrentContext = AENULL;
AERenderContext *AERenderContext::m_lpMainContext = AENULL;

AERenderContext::AERenderContext( void )
{
	m_fPriority = DEFAULT_PRIORITY;
	m_lpContextCamera = 0L;
	m_lpRenderLoop = 0L;
	m_lpContextName = 0L;

	m_bRenderingEnabled = AEFALSE;
	m_bRendersIntoBackBuffer = AEFALSE;
	m_nRenderFlags = 0;
	m_nShaderFlags = 0;

	m_nViewportSize[0] = -1;
	m_nViewportSize[1] = -1;

	m_fViewportZRange[0] = 0.1f;
	m_fViewportZRange[1] = 100.0f;

	m_fFOV[0] = 0.0f;
	m_fFOV[1] = 45.0f;

	for( int i=0; i<AE_MAX_NUM_RENDERTARGETS; i++ )
		m_spRenderTargets[i] = AENULL;

	m_spViewProps = AENULL;

	_init();
}

AERenderContext::AERenderContext( const AECamera *lpCamera, AEFLOAT32 fFovX, AEFLOAT32 fFovY, AEINT32 nWidth, AEINT32 nHeight, AEFLOAT32 fNearClip, AEFLOAT32 fFarClip, AEINT32 nRenderFlags )
{
	m_fPriority = DEFAULT_PRIORITY;
	m_lpContextCamera = (AECamera *)lpCamera;
	m_lpRenderLoop = 0L;
	m_lpContextName = 0L;

	m_bRenderingEnabled = AEFALSE;
	m_bRendersIntoBackBuffer = AEFALSE;
	m_nRenderFlags = nRenderFlags;
	m_nShaderFlags = 0;

	m_nViewportSize[0] = nWidth;
	m_nViewportSize[1] = nHeight;

	m_fViewportZRange[0] = 0.1f;
	m_fViewportZRange[1] = 100.0f;

	m_fFOV[0] = 0.0f;
	m_fFOV[1] = 45.0f;

	for( int i=0; i<AE_MAX_NUM_RENDERTARGETS; i++ )
		m_spRenderTargets[i] = AENULL;

	_init();
}

AERenderContext::~AERenderContext( void )
{
	if( m_lpContextName != AENULL )
		delete [] m_lpContextName;
}

AERenderContext *AERenderContext::GetCurrentContext( void )
{
	return m_lpCurrentContext;
}

AERenderContext *AERenderContext::GetMainRenderContext( void )
{
	return m_lpMainContext;
}

AEBOOL32 AERenderContext::IsRenderIntoBackBuffer( void ) const
{
	return m_bRendersIntoBackBuffer;
}

void AERenderContext::SetCamera( const AECamera *lpCamera )
{
	m_lpContextCamera = (AECamera *)lpCamera;
}

const char *AERenderContext::GetContextName( void ) const
{
	return m_lpContextName;
}

void AERenderContext::SetContextName( const char *lpszNewString )
{
	if( m_lpContextName != 0L )
		delete [] m_lpContextName;

	m_lpContextName = new char[ strlen(lpszNewString) + 1 ];
	strcpy( m_lpContextName, lpszNewString );
}

void AERenderContext::GetViewportSize( AEINT32 &nWidth, AEINT32 &nHeight ) const
{
	nWidth = m_nViewportSize[0];
	nHeight = m_nViewportSize[1];
}

void AERenderContext::GetViewport( AEINT32 &nPosX, AEINT32 &nPosY, AEINT32 &nWidth, AEINT32 &nHeight, AEFLOAT32 &fNear, AEFLOAT32 &fFar ) const
{
	nPosX = m_nViewportPos[0];
	nPosY = m_nViewportPos[1];

	nWidth = m_nViewportSize[0];
	nHeight = m_nViewportSize[1];

	fNear = m_fViewportZRange[0];
	fFar = m_fViewportZRange[1];
}

void AERenderContext::GetFOV( AEFLOAT32 &fFovX, AEFLOAT32 &fFovY ) const
{
	fFovX = m_fFOV[0];
	fFovY = m_fFOV[1];
}

void AERenderContext::GetClipPlanes( AEFLOAT32 &fNearClipDist, AEFLOAT32 &fFarClipDist ) const
{
	fNearClipDist = m_fViewportZRange[0];
	fFarClipDist = m_fViewportZRange[1];
}

AEBOOL32 AERenderContext::IsRenderingEnabled( void ) const
{
	return m_bRenderingEnabled;
}

AERenderLoopI *AERenderContext::GetRenderLoop( void ) const
{
	return m_lpRenderLoop;
}

void AERenderContext::SetPriority( AEFLOAT32 fPriority )
{
	m_fPriority = fPriority;
}

void AERenderContext::SetRenderFlags( AEINT32 nFlags )
{
	m_nRenderFlags = nFlags;
}

const AEMatrix4f &AERenderContext::GetProjectionMatrix( void ) const
{
	return m_spViewProps.GetPtr()->GetProjectionMatrix();
}

void AERenderContext::SetRenderLoop( AERenderLoopI *lpRenderLoop )
{
	m_lpRenderLoop = lpRenderLoop;
}

AECamera *AERenderContext::GetCamera( void ) const
{
	return m_lpContextCamera;
}

void AERenderContext::Execute( void )
{
	m_lpRenderLoop->OnDoRenderLoop( 0L );
}

void AERenderContext::SetCustomProjectionMatrix( const AEMatrix4f *lpMatrix, AEBOOL32 bAutoFrustum )
{
	if( lpMatrix != AENULL )
	{
		m_spViewProps->SetProjectionType( AEPROJECTIONTYPE_CUSTOM );
		m_spViewProps->SetCustomProjection( *lpMatrix );
	}
	else
	{
		// Ripristino matrice di default
	}
}

AETexture *AERenderContext::GetRenderTarget( AEINT32 nRenderTargetIndex, AEINT32 *lpFaceOrIndex ) const
{
	AEASSERT_MSG( nRenderTargetIndex < AE_MAX_NUM_RENDERTARGETS, "AERenderContext::GetRenderTarget: Indice troppo grande" );

	//if( this == AEngine::GetMainRenderContext() )
		//return AENULL;

	return m_spRenderTargets[ nRenderTargetIndex ];
}
